package com.example.jasonrpc.client.byRegistry;

import com.example.jasonrpc.client.TransportSelector;
import com.example.jasonrpc.common.ReflectionUtils;
import com.example.jasonrpc.proto.Peer;
import com.example.jasonrpc.registry.RegistryDirectory;
import com.example.jasonrpc.transport.TransportClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * 同样是随机连接服务主机，只不过是在服务名下的主机
 */
public class RandomSelectorByRegistry implements TransportSelector {
    private static final Logger log = LoggerFactory.getLogger(RandomSelectorByRegistry.class);
    private Map<String, List<TransportClient>> clients;

    public RandomSelectorByRegistry() {
        this.clients = new HashMap<>();
    }

    @Override
    public synchronized void init(List<RegistryDirectory> directories, int count, Class<? extends TransportClient> clazz) {
        count = Math.max(count, 1);
        for (RegistryDirectory directory : directories) {
            List<TransportClient> addresses = new ArrayList<>();
            List<Peer> peers = directory.getPeers();
            for (Peer peer : peers) {
                for (int i = 0; i < count; i++) {
                    TransportClient client = ReflectionUtils.newInstance(clazz);
                    client.connect(peer);
                    addresses.add(client);
                }
                log.info("connect server: " + peer);
            }
            clients.put(directory.getServiceClass(), addresses);
        }
    }

    @Override
    public synchronized TransportClient select(String serviceClass) {
        List<TransportClient> transportClients = clients.get(serviceClass);
        int n = new Random().nextInt(transportClients.size());
        return transportClients.remove(n);
    }

    @Override
    public synchronized void release(TransportClient client, String serviceClass) {
        clients.get(serviceClass).add(client);
    }

    @Override
    public synchronized void close() {
        for (List<TransportClient> transportClients : clients.values()) {
            for (TransportClient client : transportClients) {
                client.close();
            }
        }
        clients.clear();
    }
}
